package com.chen.authserver.v1.service;

import com.chen.authserver.constant.RespCode;
import com.chen.authserver.exception.ServiceException;
import com.chen.authserver.exception.TokenParseFailureException;
import com.chen.authserver.exception.VerifySignUpException;
import com.chen.authserver.resp.SignInBody;
import com.chen.authserver.resp.SignUpBody;
import com.chen.authserver.utils.JwtUtils;
import com.chen.authserver.utils.RegexUtils;
import com.chen.authserver.v1.DO.FinalAuthUser;
import com.chen.authserver.v1.VO.AuthUserVO;
import com.chen.authserver.v1.repository.UserMysqlRepository;
import com.chen.jeneral.utils.DateUtils;
import com.chen.jeneral.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import static com.chen.authserver.constant.RespCode.*;

@Slf4j
@Service
public class UserService {

    @Autowired
    UserMysqlRepository userMysqlRepository;

    @Autowired
    UserVerifyService userVerifyService;

    @Autowired
    TokenService tokenService;

    @Autowired
    JwtUtils jwtUtils;

    public FinalAuthUser findUser(String userAccount) {
        FinalAuthUser finalAuthUser = userMysqlRepository.find(userAccount);
        return finalAuthUser;
    }

    public AuthUserVO findUserByQuery(String query) {

        if (query == null)
            return null;

        AuthUserVO tsUser = null;
        boolean isPhoneNum = RegexUtils.checkPhoneNumber(query);
        if (isPhoneNum) {
            tsUser = userMysqlRepository.findByPhoneNum2(query);
        } else {
            tsUser = userMysqlRepository.find2(query);
        }

        return tsUser;
    }

    public void userSignUp(SignUpBody signUpBody) throws ServiceException {
        log.info("user sign up service start : " + signUpBody.getAccountName());
        checkUserInfo(signUpBody);
        saveUserInfo(signUpBody);
        log.info("user sign up service end : " + signUpBody.getAccountName());
    }

    public String userSignIn(SignInBody signInBody) throws ServiceException {
        log.info("user sign in service start : " + signInBody.getAccount());

        String token;
        if (userVerifyService.verifyAccountAndPwd(signInBody.getAccount(), signInBody.getPwd())) {
            FinalAuthUser finalAuthUser = findUser(signInBody.getAccount());
            token = tokenService.generateToken(finalAuthUser);
        } else {
            throw new ServiceException(RespCode.ACCOUNTPWD_VERIFY_FAIL_CODE, ACCOUNTPWD_VERIFY_FAIL_MSG);
        }
        log.info("user sign in service end : " + signInBody.getAccount());
        return token;
    }

    public void userSignOut(String account, String accessToken) throws ServiceException {
        log.info("user sign out service start : " + account);

        try {
            Map<String, Object> userInfoMap = jwtUtils.parseJWT(accessToken);

        } catch (TokenParseFailureException e) {
            log.error(e.toString());
        }

        log.info("user sign out service end : " + account);
    }

    private String generateNickName() {
        String uuid = UUID.randomUUID().toString().substring(0, 6);
        return "ua_" + uuid;
    }

    private void saveUserInfo(SignUpBody signUpBody) throws ServiceException {
        FinalAuthUser finalAuthUser = new FinalAuthUser();
        finalAuthUser.setAccountName(signUpBody.getAccountName());
        finalAuthUser.setEmail(signUpBody.getEmail());
        if (!StringUtils.isNullOrEmpty(signUpBody.getNickName())) {
            finalAuthUser.setNickName(signUpBody.getNickName());
        } else {
            finalAuthUser.setNickName(generateNickName());
        }
        finalAuthUser.setPwd(StringUtils.EncodeByMD5(signUpBody.getPwd()));
        finalAuthUser.setPhoneNumber(signUpBody.getPhoneNum());
        finalAuthUser.setIdCard(signUpBody.getIDCard());
        finalAuthUser.setCreateTime(new Date());

        String[] birthAndSex = getBirthAndSexByIdNo(signUpBody.getIDCard());
        try {
            finalAuthUser.setBirthDay(DateUtils.strToDate(birthAndSex[0] + " 23:59:59"));
        } catch (ParseException e) {
            log.error(e.toString());
        }

        // 客户传递的性别，可能客户故意写假性别，所以单独存储；
        finalAuthUser.setTsex(signUpBody.getSex());
        // 根据身份证号判断的真实性别
        finalAuthUser.setSex(Integer.valueOf(birthAndSex[1]));

        try {
            log.debug("New User's info start to save :" + signUpBody);
            userMysqlRepository.save(finalAuthUser);
            log.debug("New User has been saved successfully.");
        } catch (Exception e) {
            log.error(e.toString());
            throw new ServiceException(FAILURE, "注册失败！");
        }
    }

    private void checkUserInfo(SignUpBody signUpBody) throws ServiceException {
        if (!RegexUtils.checkAccount(signUpBody.getAccountName())) {
            log.info("user register service -> account verify fail:" + ACCOUNT_VERIFY_FAIL_CODE);
            throw new VerifySignUpException(ACCOUNT_VERIFY_FAIL_CODE, ACCOUNT_VERIFY_FAIL_MSG);
        }

        if (!RegexUtils.checkEmail(signUpBody.getEmail())) {
            log.info("user register service -> email verify fail:" + EMAIL_VERIFY_FAIL_CODE);
            throw new VerifySignUpException(EMAIL_VERIFY_FAIL_CODE, EMAIL_VERIFY_FAIL_MSG);
        }

        if (!RegexUtils.checkPhoneNumber(signUpBody.getPhoneNum())) {
            log.info("user register service -> phonenumber verify fail:" + PHONENUM_VERIFY_FAIL_CODE);
            throw new VerifySignUpException(PHONENUM_VERIFY_FAIL_CODE, PHONENUM_VERIFY_FAIL_MSG);
        }

        if (!RegexUtils.checkIdCard(signUpBody.getIDCard())) {
            log.info("user register service -> IDCard verify fail:" + IDCARD_VERIFY_FAIL_CODE);
            throw new VerifySignUpException(IDCARD_VERIFY_FAIL_CODE, IDCARD_VERIFY_FAIL_MSG);
        }

        if (!RegexUtils.checkPwd(signUpBody.getPwd())) {
            log.info("user register service -> pwd verify fail:" + PWD_VERIFY_FAIL_CODE);
            throw new VerifySignUpException(PWD_VERIFY_FAIL_CODE, PWD_VERIFY_FAIL_MSG);
        }

        if (isExistofAccount(signUpBody.getAccountName())) {
            log.info("user register service -> account existed :" + ACCOUNT_EXISTED_CODE);
            throw new ServiceException(ACCOUNT_EXISTED_CODE, ACCOUNT_EXISTED_MSG);
        }

        if (isExistofPhoneNum(signUpBody.getPhoneNum())) {
            log.info("user register service -> phonenum existed :" + PHONENUM_EXISTED_CODE);
            throw new ServiceException(PHONENUM_EXISTED_CODE, PHONENUM_EXISTED_MSG);
        }

        if (isExistofIdcard(signUpBody.getIDCard())) {
            log.info("user register service -> idcard existed :" + IDCARD_EXISTED_CODE);
            throw new ServiceException(IDCARD_EXISTED_CODE, IDCARD_EXISTED_MSG);
        }

        if (isExistofEmail(signUpBody.getEmail())) {
            log.info("user register service -> email existed :" + EMAIL_EXISTED_CODE);
            throw new ServiceException(EMAIL_EXISTED_CODE, EMAIL_EXISTED_MSG);
        }
    }

    private boolean isExistofPhoneNum(String phoneNum) {
        Integer id = userMysqlRepository.findIdByPhoneNum(phoneNum);
        return id != null;
    }

    private boolean isExistofAccount(String accountName) {
        Integer id = userMysqlRepository.findId(accountName);
        return id != null;
    }

    private boolean isExistofEmail(String email) {
        Integer id = userMysqlRepository.findIdByEmail(email);
        return id != null;
    }

    private boolean isExistofIdcard(String idcard) {
        Integer id = userMysqlRepository.findIdByIdCard(idcard);
        return id != null;
    }

    /**
     * 通过身份证号获取生日和性别
     *
     * @param identifyNumber
     * @return
     */
    private String[] getBirthAndSexByIdNo(String identifyNumber) {
        String dateOfBirth = null;
        String gender = null;
        //通过身份证获取性别和生日
        if (identifyNumber != null && !"".equals(identifyNumber)) {
            if (identifyNumber.length() == 15) {
                dateOfBirth = "19" + identifyNumber.substring(6, 8) + "-" + identifyNumber.substring(8, 10) + "-" + identifyNumber.substring(10, 12);
                gender = identifyNumber.substring(14, 15);
                /*基数为男 偶数为女*/
                if (Integer.parseInt(gender) % 2 == 0) {
                    gender = "1";
                } else {
                    gender = "0";
                }
            } else if (identifyNumber.length() == 18) {
                dateOfBirth = identifyNumber.substring(6, 10) + "-" + identifyNumber.substring(10, 12) + "-" + identifyNumber.substring(12, 14);
                gender = identifyNumber.substring(16, 17);
                /*基数为男 偶数为女*/
                if (Integer.parseInt(gender) % 2 == 0) {
                    gender = "1";
                } else {
                    gender = "0";
                }
            }
        }
        String[] strings = new String[]{dateOfBirth, gender};
        return strings;
    }
}
